package libra.predicate;

import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ServerWebExchange;

/**
 * Predicate断言测试控制器
 * 
 * Gateway是基于SpringWebflux开发的
 * 这部分和SpringMVC一样，可以使用SpringMVC的注解编写Controller
 * 本次Gateway&SpringBoot案例为了少起一个boot应用实例，测试方便。
 * 就直接在工程中写了个简易的Controller模拟请求
 */
@RestController
public class PredicateController {
	@RequestMapping("after")
	public Object after() {
		return Map.of("method", "after");
	}
	@RequestMapping("before")
	public Object before() {
		return Map.of("method", "before");
	}
	@RequestMapping("between")
	public Object between() {
		return Map.of("method", "between");
	}
	
	@RequestMapping("cookie")
	public Object cookie() {
		return Map.of("method", "cookie");
	}
	@RequestMapping("header")
	public Object header() {
		return Map.of("method", "header");
	}
	@RequestMapping("method")
	public Object method() {
		return Map.of("method", "method");
	}
	@RequestMapping("path")
	public Object path() {
		return Map.of("method", "path");
	}
	@RequestMapping("path/{rest}")
	public Object path_rest( @PathVariable("rest") String val ) {
		return Map.of("method", "path_rest", "val", val);
	}
	@RequestMapping("query")
	public Object query( String param ) {
		return Map.of("method", "query", "param", param);
	}
	
	@RequestMapping("remoteAddr")
	public Object remoteAddr( ServerWebExchange serverWebExchange ) {
		return Map.of("method", "remoteAddr", "ip", getIp(serverWebExchange));
	}
	private String getIp(ServerWebExchange serverWebExchange){
        ServerHttpRequest request = serverWebExchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个ip值，第一个ip才是真实ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        return ip.replaceAll(":", ".");
    }
	
	@RequestMapping("host")
	public Object host( ServerWebExchange serverWebExchange ) {
		return Map.of("method", "host", "host", serverWebExchange.getRequest().getHeaders().getHost());
	}
	
	int sum = 0, high = 0, low = 0;
	@RequestMapping("high/weight")
	public Object weight_hign( ServerWebExchange serverWebExchange ) {
		return Map.of("method", "weight_hign", "sum", ++sum, "high", ++high, "low", low);
	}	
	@RequestMapping("low/weight")
	public Object weight_low( ServerWebExchange serverWebExchange ) {
		return Map.of("method", "weight_low", "sum", ++sum, "high", high, "low", ++low);
	}
	
	
	@RequestMapping("selfPredicate")
	public Object selfPredicate( ServerWebExchange serverWebExchange ) {
		return Map.of("method", "selfPredicate",
				"type", serverWebExchange.getRequest().getMethod(),
				"cookie", serverWebExchange.getRequest().getCookies(), 
				"param", serverWebExchange.getRequest().getQueryParams());
	}
	
	@RequestMapping("outterSelfPredicate")
	public Object outterSelfPredicate( ServerWebExchange serverWebExchange ) {
		return Map.of("method", "outterSelfPredicate");
	}
}
